#!/usr/bin/python
import pygame
import board, chessman, predef, guifaimage, guifawidget
from board import *
from chessman import *
from predef import *
from guifawidget import *


class LiveGroup(pygame.sprite.OrderedUpdates):
    def __init__(self):
        return pygame.sprite.OrderedUpdates.__init__(self)

    def draw(self, Surface):
        for i in self.sprites():
            Surface.blit(i.image, i.rect)
            if i.resurgence > 0:
                Surface.blit(self.resurgence_image, i.rect)

class FieldGroup(pygame.sprite.OrderedUpdates):
    def __init__ (self):
        return pygame.sprite.OrderedUpdates.__init__(self)
    def draw (self, Surface, type):
        for s in self.sprites():
            if not s.inhibited and is_inboard(s.rect[0], s.rect[1]):
                if s.type in type:
                    Surface.blit(s.image, s.rect)

class NormalGroup(pygame.sprite.OrderedUpdates):
    def __init__(self):
        return pygame.sprite.OrderedUpdates.__init__(self)
    def draw(self, Surface):
        sealimg = self.gfimages.get_image("seal_flag.png")
        for s in self.sprites():
            Surface.blit(s.image, s.rect)
            if s.seal:
                Surface.blit(sealimg, s.rect)

class DeadChessManGroup(pygame.sprite.OrderedUpdates):
    def __init__(self, *sprites):
        self.font = pygame.font.SysFont("Arial", 12)
        self.corpseboard = [[0 for x in range(11)] for y in range(11)]
        return pygame.sprite.OrderedUpdates.__init__(self, sprites)

    def draw(self, Surface):
        for i in self.sprites():
            Surface.blit(i.image, i.rect)
        for i in range(0, 11):
            for j in range(0, 11):
                if self.corpseboard[i][j] > 0:
                    number = self.font.render(str(self.corpseboard[i][j]), True, (0,0,255))
                    Surface.blit(self.corpse_flag, (i*CHESSSIZE, j*CHESSSIZE))
                    Surface.blit(number, (i*CHESSSIZE+50, j*CHESSSIZE+50))
                    del number

    def add_corpse(self, sprite):
        i = sprite.rect[0]//CHESSSIZE
        j = sprite.rect[1]//CHESSSIZE
        self.corpseboard[i][j] = self.corpseboard[i][j] + 1
        pygame.sprite.OrderedUpdates.add(self, sprite)

    def remove_corpse(self, sprite):
        i = sprite.rect[0]//CHESSSIZE
        j = sprite.rect[1]//CHESSSIZE
        self.corpseboard[i][j] = self.corpseboard[i][j] - 1
        pygame.sprite.OrderedUpdates.remove(self, sprite)

    def empty_corpse(self):
        self.corpseboard = [[0 for x in range(11)] for y in range(11)]
        pygame.sprite.OrderedUpdates.empty(self)


class GuifaGame:
    def __init__(self, gfimages, gfsounds):
        self.gfimages = gfimages
        self.gfsounds = gfsounds
        self.board = ChessBoard()
        self.playerlist = [PLAYER1, PLAYER2, PLAYER3, PLAYER4]
        self.normalgroup = NormalGroup()  # for both living and walkingdead
        self.normalgroup.gfimages = gfimages
        self.deadgroup = DeadChessManGroup() #pygame.sprite.OrderedUpdates()
        self.deadgroup.corpse_flag = self.gfimages.get_image("corpse_flag.png")
        self.fieldgroup = FieldGroup()   # for forcefield and enchantment
        self.flaggroup = pygame.sprite.OrderedUpdates()    # for movement flag and attack flag (helper, not chess)
        self.current_player = self.playerlist[0]
        self.cur_selected_chess = None
        self.action_state = ACTION_MOVE
        self.action_chess = None
        self.corpsesel = None

        #for asynchronous chess state update
        self.updatelist = []
        self.lockupdate =False

    def reset(self):
        pass

    def set_player(self, player):
        if player in self.playerlist:
            self.current_player = player
            self.unselect_chess()

    def _remove_player(self, player):
        self.playerlist.remove(player)

    def next_player(self):
        index = self.playerlist.index(self.current_player)
        self.current_player = self.playerlist[(index+1)%len(self.playerlist)]
        self.unselect_chess()

    def get_current_player(self):
        return self.current_player

    def add_live(self, owner, kind, x, y):
        chess = ChessLiving(owner, kind)
        filename = owner + "_" + kind + ".png"
        chess.image = self.gfimages.get_image(filename)
        chess.rect = chess.image.get_rect()
        chess.rect[0], chess.rect[1] = board_to_screen(x, y)
        self.board.append_chess(chess, x, y)
        self.normalgroup.add(chess)

        if kind == KIND_SOOTHSAYER:
            chess.targetseal = None

        #on add
        self.update_inhibited(chess)

        return chess

    def add_dead(self, kind, x, y):
        chess = ChessCropse(kind)
        filename = "corpse_" + kind + ".png"
        chess.image = self.gfimages.get_image(filename)
        chess.rect = chess.image.get_rect()
        chess.rect[0], chess.rect[1] = board_to_screen(x, y)
        self.board.append_chess(chess, x, y)
        self.deadgroup.add_corpse(chess)
        #self.update_inhibited(chess)
        return chess

    def add_walkingdead(self, owner, kind, x, y):
        chess = ChessWalkingDead(owner, kind)
        filename = owner + "_" + kind + ".png"
        chess.image = pygame.Surface.copy(self.gfimages.get_image(filename))
        #pygame.Surface.blit(self.gfimages.get_image("resurgence_flag.png"), chess.image)
        chess.image.blit(self.gfimages.get_image("resurgence_flag.png"), (0, 0))
        chess.rect = chess.image.get_rect()
        chess.rect[0], chess.rect[1] = board_to_screen(x, y)
        self.board.append_chess(chess, x, y)
        self.normalgroup.add(chess)

        if kind == KIND_SOOTHSAYER:
            chess.targetseal = None

        self.update_inhibited(chess)
        return chess

    def add_summons(self, father, x, y):
        chess = ChessSummons(father.owner)
        filename = father.owner + "_" + "summons.png"
        chess.image = self.gfimages.get_image(filename)
        chess.rect = chess.image.get_rect()
        chess.rect[0], chess.rect[1] = board_to_screen(x, y)
        chess.father = father
        father.children.append(chess)
        self.board.append_chess(chess, x, y)
        self.normalgroup.add(chess)
        self.update_inhibited(chess)
        return chess

    def add_clone(self, father, x, y):
        chess = ChessClone(father.owner)
        filename = father.owner + "_" + "illusionist.png"
        chess.image = pygame.Surface.copy(self.gfimages.get_image(filename))
        chess.image.blit(self.gfimages.get_image("clone_flag.png"), (0, 0))
        chess.rect = chess.image.get_rect()
        chess.rect[0], chess.rect[1] = board_to_screen(x, y)
        chess.father = father
        father.children.append(chess)
        self.board.append_chess(chess, x, y)
        self.normalgroup.add(chess)
        self.update_inhibited(chess)
        return chess

    def add_field(self, father, x, y):
        chess = ChessField(father.owner)
        filename = "forcefield_flag.png"
        chess.image = pygame.Surface.copy(self.gfimages.get_image(filename))
        chess.rect = chess.image.get_rect()
        chess.rect[0], chess.rect[1] = board_to_screen(x, y)
        chess.father = father
        father.children.append(chess)
        self.board.append_chess(chess, x, y)
        self.fieldgroup.add(chess)
        self.update_inhibited(chess)
        return chess

    def add_enchantment(self, father, x, y):
        chess = ChessEnchantment(father.owner)
        filename = "enchantment_flag.png"
        chess.image = pygame.Surface.copy(self.gfimages.get_image(filename))
        chess.rect = chess.image.get_rect()
        chess.rect[0], chess.rect[1] = board_to_screen(x, y)
        chess.father = father
        father.children.append(chess)
        self.board.append_chess(chess, x, y)
        self.fieldgroup.add(chess)
        self.update_inhibited(chess)
        return chess

    def add_enchantment_ad(self, father, x, y):
        chess = ChessEnchantmentAd(father.owner)
        filename = "enchantment_ad_flag.png"
        chess.image = pygame.Surface.copy(self.gfimages.get_image(filename))
        chess.rect = chess.image.get_rect()
        chess.rect[0], chess.rect[1] = board_to_screen(x, y)
        chess.father = father
        father.children.append(chess)
        self.board.append_chess(chess, x, y)
        self.fieldgroup.add(chess)
        self.update_inhibited(chess)
        return chess

    def remove_children(self, chess):
        while len(chess.children) != 0:
            c = chess.children.pop()
            self.remove_chess(c)

    def remove_chess(self, chess):
        m, n = screen_to_board(chess.rect[0], chess.rect[1])
        if chess.type in (TYPE_NORMAL, TYPE_SUMMONS, TYPE_CLONE):
            self.normalgroup.remove(chess)
        elif chess.type in (TYPE_FIELD, TYPE_ENCHANTMENT, TYPE_ENCHANTMENT_AD):
            self.fieldgroup.remove(chess)
        elif chess.type == TYPE_CORPSE:
            self.deadgroup.remove_corpse(chess)
        else:
            raise TypeError

        self.board.remove_chess(chess, m, n)
        self.remove_children(chess)
        for c2 in self.board.chesslist(m, n):
            self.update_inhibited(c2)

    def create_field_area(self, chess):
        if chess.kind != KIND_FORCEFIELDER:
            raise TypeError
        if chess.seal:
            return
        # (x, y) is the center of this area
        x, y = screen_to_board(chess.rect[0], chess.rect[1])
        pointlist = []
        if chess.owner == PLAYER1 or chess.owner == PLAYER3:
            for n in range(x-1, x+2):
                pointlist.append((n, y))
        else:
            for n in range(y-1, y+2):
                pointlist.append((x, n))

        oldchildren = []
        oldchildren.extend(chess.children)
        for p in pointlist:
            newchess = self.add_field(chess, p[0], p[1])
        for c in oldchildren:
            if c.type == TYPE_FIELD:
                chess.children.remove(c)
                self.remove_chess(c)

    def create_field_ad_area(self, chess):
        if chess.kind != KIND_FORCEFIELDER:
            raise TypeError
        if chess.seal:
            return
        # (x, y) is the center of this area
        x, y = screen_to_board(chess.rect[0], chess.rect[1])

        oldchildren = []
        oldchildren.extend(chess.children)
        for m in range(x-1, x+2):
            for n in range(y-1, y+2):
                newchess = self.add_field(chess, m, n)
        for c in oldchildren:
            if c.type == TYPE_FIELD:
                chess.children.remove(c)
                self.remove_chess(c)

    def create_enchantment_area(self, chess):
        if chess.kind != KIND_SOOTHSAYER:
            raise TypeError
        if chess.seal:
            return
        # (x, y) is the center of this area
        x, y = screen_to_board(chess.rect[0], chess.rect[1])
        oldchildren = []
        oldchildren.extend(chess.children)
        for m in range(x-1, x+2):
            for n in range(y-1, y+2):
                newchess = self.add_enchantment(chess, m, n)
        for c in oldchildren:
            if c.type == TYPE_ENCHANTMENT:
                chess.children.remove(c)
                self.remove_chess(c)


    def create_enchantment_ad_area(self, chess, x, y):
        if chess.kind != KIND_SOOTHSAYER:
            raise TypeError
        if chess.seal:
            return

        # (x, y) is the top left corner of this area
        oldchildren = []
        oldchildren.extend(chess.children)
        for m in range(x, x+2):
            for n in range(y, y+2):
                newchess = self.add_enchantment_ad(chess, m, n)
        for c in oldchildren:
            if c.type == TYPE_ENCHANTMENT_AD:
                chess.children.remove(c)
                self.remove_chess(c)

    def destroy_field_area(self, chess):
        if chess.kind != KIND_FORCEFIELDER:
            raise TypeError
        while len(chess.children) != 0:
            c = chess.children.pop()
            self.remove_chess(c)


    def destroy_field_ad_area(self, chess):
        if chess.kind != KIND_FORCEFIELDER:
            raise TypeError
        self.destroy_field_area(chess)

    def destroy_enchantment_area(self, chess):
        if chess.kind != KIND_SOOTHSAYER:
            raise TypeError
        list = []
        while len(chess.children) != 0:
            if chess.children[-1].type != TYPE_ENCHANTMENT:
                list.append(chess.children.pop())
                continue
            c = chess.children.pop()
            self.remove_chess(c)
        chess.children = list

    def destroy_enchantment_ad_area(self, chess):
        if chess.kind != KIND_SOOTHSAYER:
            raise TypeError
        list = []
        while len(chess.children) != 0:
            if chess.children[-1].type != TYPE_ENCHANTMENT_AD:
                list.append(chess.children.pop())
                continue
            c = chess.children.pop()
            self.remove_chess(c)
        chess.children = list

    def put_movement_flag(self, x, y):
        flag = pygame.sprite.Sprite()
        flag.type = TYPE_FLAG_MOVEMENT
        filename = "movement_flag.png"
        flag.image = self.gfimages.get_image(filename)
        flag.rect = flag.image.get_rect()
        flag.rect[0], flag.rect[1] = board_to_screen(x, y)
        self.flaggroup.add(flag)

    def put_attack_flag(self, x, y):
        flag = pygame.sprite.Sprite()
        flag.type = TYPE_FLAG_ATTACK
        filename = "attack_flag.png"
        flag.image = self.gfimages.get_image(filename)
        flag.rect = flag.image.get_rect()
        flag.rect[0], flag.rect[1] = board_to_screen(x, y)
        self.flaggroup.add(flag)

    def put_select_flag(self, x, y):
        flag = pygame.sprite.Sprite()
        flag.type = TYPE_FLAG_SELECT
        filename = "cur2.png"
        flag.image = self.gfimages.get_image(filename)
        flag.rect = flag.image.get_rect()
        flag.rect[0], flag.rect[1] = board_to_screen(x, y)
        self.flaggroup.add(flag)

    def select_chess(self, chess):
        self.cur_selected_chess = chess
        self.clear_flag()
        x, y = screen_to_board(chess.rect[0], chess.rect[1])
        self.put_select_flag(x, y)
        self.calculate_movement_flag(self.cur_selected_chess)
        self.gfsounds.get_sound("select").play()

    def unselect_chess(self):
        self.cur_selected_chess = None
        self.clear_flag()

    def resurgence_chess(self):
        pass

    def kill_chess(self, chess):
        x, y = screen_to_board(chess.rect[0], chess.rect[1])
        self.on_chess_killed(chess)
        self.remove_chess(chess)
        if chess.father != None:
            chess.father.children.remove(chess)
        if chess.leftcorpse:
            self.add_dead(chess.kind, x, y)
        del chess
        self.gfsounds.get_sound("kill").play()

    def field_kill_chess(self, chess):
        if chess.type != TYPE_FIELD:
            raise TypeError
        x, y = screen_to_board(chess.rect[0], chess.rect[1])
        for c in self.board.chesslist(x, y):
            if c.isEnemy(chess.owner) and c.isCreature():
                self.kill_chess(c)
                break

    def crush_chess(self, chess):
        x, y = screen_to_board(chess.rect[0], chess.rect[1])
        self.on_chess_killed(chess)
        self.remove_chess(chess)
        if chess.father != None:
            chess.father.children.remove(chess)
        del chess
        self.gfsounds.get_sound("kill").play()

    def seal_chess(self, chess):
        x, y = screen_to_board(chess.rect[0], chess.rect[1])
        chess.seal = True
        if chess.kind not in (KIND_SUMMONER,):
            self.remove_children(chess)

    def unseal_chess(self, chess):
        chess.seal = False
        self.recalculate_chess_state(chess)

    def dismember_corpse(self, x, y):
        ret = False
        corpselist = self.board.chesslist(x, y)[:]
        for c in corpselist:
            if c.type == TYPE_CORPSE:
                self.remove_chess(c)
                ret = True
        return ret

    def have_corpse(self, x, y):
        for c in self.board.chesslist(x, y):
            if c.type == TYPE_CORPSE:
                return True
        return False

    def check_action(self, x, y):
        move = False
        attack = False
        for f in self.flaggroup:
            if screen_to_board(f.rect[0], f.rect[1]) == (x, y):
                if f.type == TYPE_FLAG_ATTACK:
                    attack = True
                    break;
                else:
                    move = True
                    break;

        return move, attack

    def move_chess_step(self, chess, x, y):
        oldx, oldy = screen_to_board(chess.rect[0], chess.rect[1])
        self.board.remove_chess(chess, oldx, oldy)

        updatelist = []
        if chess.kind == KIND_SCEPTRE:
            aroundlist = self.get_around(chess, KIND_FORCEFIELDER)
            if aroundlist != None:
                updatelist.extend(aroundlist)

        chess.rect[0], chess.rect[1] = board_to_screen(x, y)
        self.board.append_chess(chess, x, y)

        isinhibited = chess.inhibited
        self.update_inhibited(chess)
        if isinhibited == chess.inhibited:
            self.recalculate_chess_state(chess)

        for c in updatelist:
            isinhibited = c.inhibited
            self.update_inhibited(c)
            if isinhibited == c.inhibited:
                self.recalculate_chess_state(c)

        if chess.kind == KIND_SCEPTRE:
            aroundlist = self.get_around(chess, KIND_FORCEFIELDER)
            if aroundlist != None:
                for c in aroundlist:
                    isinhibited = c.inhibited
                    self.update_inhibited(c)
                    if isinhibited == c.inhibited:
                        self.recalculate_chess_state(c)
        elif chess.kind == KIND_SOOTHSAYER:
            if chess.targetseal != None:
                self.unseal_chess(chess.targetseal)
                chess.targetseal = None
            if is_center(oldx, oldy):
                self.destroy_enchantment_ad_area(chess)
        elif chess.kind == KIND_ILLUSIONIST:
            self.remove_children(chess)


    def move_chess(self, chess, x, y):
        stepx = stepy = 0
        oldx, oldy = screen_to_board(chess.rect[0], chess.rect[1])
        if x > oldx:
            stepx = 1
        elif x < oldx:
            stepx = -1
        else:
            stepx = 0

        if y > oldy:
            stepy = 1
        elif y < oldy:
            stepy = -1
        else:
            stepy = 0

        #step by step...
        while oldx != x or oldy != y:
            self.move_chess_step(chess, oldx+stepx, oldy+stepy)
            oldx, oldy = screen_to_board(chess.rect[0], chess.rect[1])
        self.gfsounds.get_sound("move").play()

    def calculate_point(self, chess, x, y):
        # if something can block me
        canpass = True
        canstand = True
        canattack = False
        for c in self.board.chesslist(x, y):
            if chess.isEnemy(c.owner):
                # enemy (creature or field or enchantment)
                if c.isCreature():
                    # creature
                    canstand = False
                    if c.nonentities and not c.inhibited:
                        if chess.kind == KIND_SOOTHSAYER:
                            canattack = True
                    else:
                        # do not have ILLUSION ability
                        canattack = True
                        for c2 in self.board.chesslist(x, y):
                            if chess.isEnemy(c2.owner):
                                if c2.type == TYPE_FIELD and not c2.inhibited:
                                    if chess.kind != KIND_SOOTHSAYER:
                                        canattack = False
                                if c2.type in (TYPE_ENCHANTMENT, TYPE_ENCHANTMENT_AD) and not c2.inhibited:
                                    canpass = False
                        if not chess.nonentities:
                            # I also do not have ILLUSION ability
                            canpass = False
                else:
                    # field or enchantment
                    if c.type == TYPE_FIELD and not c.inhibited:
                        # field
                        if chess.kind != KIND_SOOTHSAYER:
                            canstand = False
                            canpass = False
                    else:
                        # enchantment
                        pass
            else:
                # self or alliance or cropse
                if c.isCreature():
                    # is creature, not field or enchantment or cropse
                    canstand = False
                    if c.nonentities and not c.inhibited:
                        for c2 in self.board.chesslist(x, y):
                            if chess.isEnemy(c2.owner):
                                if c2.type == TYPE_FIELD and not c2.inhibited:
                                    if chess.kind != KIND_SOOTHSAYER:
                                        canattack = False
                                if c2.type in (TYPE_ENCHANTMENT, TYPE_ENCHANTMENT_AD) and not c2.inhibited:
                                    canpass = False
                    else:
                        # do not have ILLUSION ability
                        if not chess.nonentities:
                            # I also do not have ILLUSION ability
                            canpass = False
                else:
                    # field or enchantment or cropse
                    pass
        if canstand:
            self.put_movement_flag(x, y)
        if canattack and chess.attacker:
            self.put_attack_flag(x, y)
        else:
            canattack = False
            
        return canpass, canattack

    def calculate_movement_flag(self, chess):
        x, y = screen_to_board(chess.rect[0], chess.rect[1])
        left = right = up = down = upleft = upright = downleft = downright = True
        attack = False
        for p in range(1, chess.movement+1):
            if right and self.board.box[x+(p-1)][y].right:
                right, attack = self.calculate_point(chess, x+p, y)
            elif right:
                right = False

            if left and self.board.box[x-(p-1)][y].left:
                left, attack = self.calculate_point(chess, x-p, y)
            elif left:
                left = False

            if down and self.board.box[x][y+(p-1)].down:
                down, attack = self.calculate_point(chess, x, y+p)
            elif down:
                down = False

            if up and self.board.box[x][y-(p-1)].up:
                up, attack = self.calculate_point(chess, x, y-p)
            elif up:
                up = False

            if upright and self.board.box[x+(p-1)][y-(p-1)].upright:
                upright, attack = self.calculate_point(chess, x+p, y-p)
            elif upright:
                upright = False

            if upleft and self.board.box[x-(p-1)][y-(p-1)].upleft:
                upleft, attack = self.calculate_point(chess, x-p, y-p)
            elif upleft:
                upleft = False

            if downright and self.board.box[x+(p-1)][y+(p-1)].downright:
                downright, attack = self.calculate_point(chess, x+p, y+p)
            elif downright:
                downright = False

            if downleft and self.board.box[x-(p-1)][y+(p-1)].downleft:
                downleft, attack = self.calculate_point(chess, x-p, y+p)
            elif downleft:
                downleft = False

    def get_around(self, chess, kind):
        #for now, only used by sceptre and forcefielder.
        x, y = screen_to_board(chess.rect[0], chess.rect[1])
        aroundlist = []
        for p in ((x-1, y-1), (x-1, y+1), (x+1, y-1), (x+1, y+1),
                (x, y-1), (x, y+1), (x-1, y), (x+1, y)):
            for c in self.board.chesslist(p[0], p[1]):
                if c.owner == chess.owner and c.kind == kind:
                    #is around chess 'kind'
                    aroundlist.append(c)
        if len(aroundlist) == 0:
            return None
        else:
            return aroundlist

    def hold_update(self):
        self.lockupdate = True

    def unhold_update(self):
        self.lockupdate = False
        for c in self.updatelist:
            self.update_inhibited(c)
        del self.updatelist
        self.updatelist = []

    def update_inhibited(self, chess):
        if self.lockupdate:
            self.updatelist.append(chess)
            return
        inhibited = False
        x, y = screen_to_board(chess.rect[0], chess.rect[1])
        for c in self.board.chesslist(x, y):
            if not c.isEnemy(chess.owner):
                continue
            if chess.isCreature():
                if chess.kind == KIND_SOOTHSAYER:
                    if c.type == TYPE_ENCHANTMENT_AD:
                        inhibited = True
                        break
                elif chess.kind == KIND_SCEPTRE:
                    pass
                else:
                    if (c.type == TYPE_ENCHANTMENT and not c.inhibited) or \
                            c.type == TYPE_ENCHANTMENT_AD:
                        inhibited = True
                        break
            else:
                if chess.type == TYPE_ENCHANTMENT:
                    if c.type == TYPE_ENCHANTMENT_AD:
                        inhibited = True
                        break
                elif chess.type == TYPE_FIELD:
                    if (c.type == TYPE_ENCHANTMENT and not c.inhibited) or \
                            c.type == TYPE_ENCHANTMENT_AD or \
                            c.type == TYPE_FIELD and not c.inhibited:
                        inhibited = True
                        break
        if chess.inhibited != inhibited:
            chess.inhibited = inhibited
            self.recalculate_chess_state(chess)
        return inhibited

    def on_chess_killed(self, chess):
        if chess.kind == KIND_SCEPTRE:
            for c in self.normalgroup.sprites():
                if c.owner == chess.owner and c != chess:
                    self.crush_chess(c)
            self._remove_player(chess.owner)
        elif chess.kind == KIND_SUMMONS:
            if len(chess.father.children) == 0:
                chess.father.attacker = True
                chess.father.upkeep = False
        elif chess.kind == KIND_ILLUSIONIST:
            if len(chess.children) == 1:
                chess.leftcorpse = False
                m, n = screen_to_board(chess.children[0].rect[0], chess.children[0].rect[1])
                self.crush_chess(chess.children[0])
                self.add_live(chess.owner, chess.kind, m, n)
        elif chess.kind == KIND_SOOTHSAYER:
            if chess.targetseal != None:
                self.unseal_chess(chess.targetseal)
            self.destroy_enchantment_ad_area(chess)

    def recalculate_chess_state(self, chess):
        x, y = screen_to_board(chess.rect[0], chess.rect[1])
        if not chess.inhibited:
            if chess.isCreature():
                if chess.kind == KIND_SOOTHSAYER:
                    self.create_enchantment_area(chess)
                elif chess.kind == KIND_FORCEFIELDER:
                    if is_center(x, y):
                        self.create_field_ad_area(chess)
                    elif self.get_around(chess, KIND_SCEPTRE) != None:
                        self.create_field_area(chess)
                    else:
                        self.destroy_field_area(chess)
            else:
                if chess.type == TYPE_FIELD:
                    self.field_kill_chess(chess)
                elif chess.type == TYPE_ENCHANTMENT:
                    for c in self.board.chesslist(x, y):
                        self.update_inhibited(c)

        else:
            if chess.isCreature():
                if chess.kind == KIND_SOOTHSAYER:
                    self.destroy_enchantment_area(chess)
                elif chess.kind == KIND_FORCEFIELDER:
                    if is_center(x, y):
                        self.create_field_ad_area(chess)
                    elif self.get_around(chess, KIND_SCEPTRE) != None:
                        self.destroy_field_area(chess)
                    else:
                        self.destroy_field_area(chess)
            else:
                if chess.type == TYPE_ENCHANTMENT:
                    for c in self.board.chesslist(x, y):
                        self.update_inhibited(c)

    def clear_flag(self):
        self.flaggroup.empty()

    def set_action_state(self, state, chess):
        self.action_chess = chess
        self.action_state = state
        self.unselect_chess()
        if state == ACTION_MOVE:
            if self.corpsesel != None:
                del self.corpsesel
                self.corpsesel = None

    def action_move(self, x, y):
        ret = False
        for chess in self.board.chesslist(x, y):
            if chess.selectable and chess.owner == self.current_player:
                self.select_chess(chess)
                break
        else:
            if self.cur_selected_chess != None:
                moveable, attackable = self.check_action(x, y)
                if moveable:
                    self.move_chess(self.cur_selected_chess, x, y)
                    self.unselect_chess()
                    ret = True
                elif attackable:
                    target = None
                    for c in self.board.chesslist(x, y):
                        if self.cur_selected_chess.isEnemy(c.owner) and not c.overlapping:
                            target = c
                            break;
                    if target != None:
                        if self.cur_selected_chess.kind == KIND_SORCERER:
                            self.crush_chess(target)
                        else:
                            self.kill_chess(target)
                        self.move_chess(self.cur_selected_chess, x, y)
                        self.unselect_chess()
                        ret = True
        return ret                        

    def action_clone(self, x, y):
        canadd = True
        for c in self.board.chesslist(x, y):
            if c.isCreature():
                canadd = False
            elif self.action_chess.isEnemy(c.owner) and not c.inhibited:
                # enemy's field or enchantment
                canadd = False
        if canadd:
            for c in self.action_chess.children:
                self.crush_chess(c)
            self.add_clone(self.action_chess, x, y)
            self.set_action_state(ACTION_MOVE, None)
            return True
        return False

    def action_exchange(self, x, y):
        m, n = screen_to_board(self.action_chess.rect[0], self.action_chess.rect[1])
        cando = True
        if self.action_chess.inhibited:
            cando = False
        if self.action_chess.seal:
            cando = False
        for c in self.board.chesslist(x, y):
            if c.owner != None and self.action_chess.isEnemy(c.owner) and not c.isCreature():
                # In enemy's enchantment
                if not c.inhibited:
                    cando = False
        for c in self.board.chesslist(x, y):
            if c.isCreature() and self.action_chess.owner == c.owner:
                if not c is self.action_chess and not c.kind == KIND_SCEPTRE:
                    if cando:
                        if self.action_chess.father != c:
                            self.move_chess_step(self.action_chess, x, y)
                        if c.father != self.action_chess:
                            self.move_chess_step(c, m, n)
                        self.set_action_state(ACTION_MOVE, None)
                        return True
        return False

    def action_summon(self, x, y):
        m, n = screen_to_board(self.action_chess.rect[0], self.action_chess.rect[1])
        if x >= m - 1 and x <= m + 1 and \
                y >= n - 1 and y <= n + 1:
            return self.action_summon_ad(x, y)
        return False

    def action_summon_ad(self, x, y):
        canadd = True
        for c in self.board.chesslist(x, y):
            if c.isCreature():
                canadd = False
                break
            elif c.isEnemy(self.action_chess.owner) and not c.inhibited:
                canadd = False
                break
        if canadd:
            self.add_summons(self.action_chess, x, y)
            self.action_chess.attacker = False
            self.action_chess.upkeep = True
        if len(self.action_chess.children) == 4:
            self.set_action_state(ACTION_MOVE, None)
            return True
        return False

    def action_resurgence(self, x, y):
        m, n = screen_to_board(self.action_chess.rect[0], self.action_chess.rect[1])
        if x >= m - 1 and x <= m + 1 and \
                y >= n - 1 and y <= n + 1:
            return self.action_resurgence_ad(x, y)
        return False

    def action_resurgence_ad(self, x, y):
        cando = False
        corpselist = []
        for c in self.board.chesslist(x, y):
            if c.type == TYPE_CORPSE:
                corpselist.append(c)
                cando = True
        for c in self.board.chesslist(x, y):
            if c.isCreature():
                cando = False
                break
            elif c.type == TYPE_CORPSE:
                pass
            elif c.isEnemy(self.action_chess.owner) and not c.inhibited:
                cando = False
                break
        if cando:
            target = corpselist[0]
            if len(corpselist) > 1:
                self.set_action_state(ACTION_SELECT_CORPSE, self.action_chess)
                sx, sy = board_to_screen(x, y)
                self.corpsesel = CorpseSelector(0, 0, corpselist)
                w = self.corpsesel.get_width()
                if sx + w > BOARD_W:
                    sx = BOARD_W - w
                self.corpsesel.set_pos(sx, sy)
            else:
                self.add_walkingdead(self.action_chess.owner, target.kind, x, y)
                self.remove_chess(target)
                self.set_action_state(ACTION_MOVE, None)
                return True
        return False

    def action_select_corpse(self, target_corpse):
        x, y = screen_to_board(target_corpse.rect[0], target_corpse.rect[1])
        self.add_walkingdead(self.action_chess.owner, target_corpse.kind, x, y)
        self.remove_chess(target_corpse)
        self.set_action_state(ACTION_MOVE, None)
        del self.corpsesel
        self.corpsesel = None

    def action_crush_ad(self, x, y):
        m, n = screen_to_board(self.action_chess.rect[0], self.action_chess.rect[1])
        cando = False
        for c in self.board.chesslist(x, y):
            if c.isCreature() and c.isEnemy(self.action_chess.owner):
                cando = True
        if m != x and n != y:
            cando = False
        if cando:
            fieldlist = []
            creaturelist = []
            for c in self.board.chesslist(x, y):
                if c.isCreature() and c.isEnemy(self.action_chess.owner):
                    creaturelist.append(c)
                elif c.isEnemy(self.action_chess.owner) and c.type == TYPE_FIELD:
                    fieldlist.append(c)
            for c in fieldlist:
                # Destroy field (remove it)
                c.father.children.remove(c)
                self.remove_chess(c)
            for c in creaturelist:
                self.crush_chess(c)
            self.move_chess_step(self.action_chess, x, y)
            self.set_action_state(ACTION_MOVE, None)
            return True
        return False

    def action_seal(self, x, y):
        for c in self.board.chesslist(x, y):
            if c.isEnemy(self.action_chess.owner) and c.isCreature():
                if self.action_chess.targetseal != None:
                    self.unseal_chess(self.action_chess.targetseal)
                    self.action_chess.targetseal = None
                self.destroy_enchantment_ad_area(self.action_chess)
                self.seal_chess(c)
                self.action_chess.targetseal = c
                self.set_action_state(ACTION_MOVE, None)
                return True
        return False

    def action_enchantment_ad(self, x, y):
        if x > 0 and x < 12 and y > 0 and y < 12:
            if self.action_chess.targetseal != None:
                self.unseal_chess(self.action_chess.targetseal)
                self.action_chess.targetseal = None
            self.create_enchantment_ad_area(self.action_chess, x, y)
            for c in self.board.chesslist(x, y):
                self.update_inhibited(c)
            for c in self.board.chesslist(x+1, y):
                self.update_inhibited(c)
            for c in self.board.chesslist(x, y+1):
                self.update_inhibited(c)
            for c in self.board.chesslist(x+1, y+1):
                self.update_inhibited(c)
            self.set_action_state(ACTION_MOVE, None)
            return True
        return False

    def click_board(self, x, y):
        if self.action_state == ACTION_MOVE:
            return self.action_move(x, y)
        elif self.action_state == ACTION_EXCHANGE:
            return self.action_exchange(x, y)
        elif self.action_state == ACTION_CLONE:
            return self.action_clone(x, y)
        elif self.action_state == ACTION_SUMMON:
            return self.action_summon(x, y)
        elif self.action_state == ACTION_SUMMON_AD:
            return self.action_summon_ad(x, y)
        elif self.action_state == ACTION_CRUSH_AD:
            return self.action_crush_ad(x, y)
        elif self.action_state == ACTION_SEAL:
            return self.action_seal(x, y)
        elif self.action_state == ACTION_ENCHANTMENT_AD:
            return self.action_enchantment_ad(x, y)
        elif self.action_state == ACTION_RESURGENCE:
            return self.action_resurgence(x, y)
        elif self.action_state == ACTION_RESURGENCE_AD:
            return self.action_resurgence_ad(x, y)
        

    def draw(self, screen):
        self.deadgroup.draw(screen)
        self.fieldgroup.draw(screen, (TYPE_ENCHANTMENT, TYPE_ENCHANTMENT_AD))
        self.normalgroup.draw(screen)
        self.fieldgroup.draw(screen, (TYPE_FIELD))
        self.flaggroup.draw(screen)
        if self.corpsesel != None:
            self.corpsesel.draw(screen)

if __name__ == "__main__":
    test = GuifaGame(guifaimage.GuifaImage())
    test.add_live(PLAYER3, KIND_FORCEFIELDER, 3, 3)
    test.add_dead(KIND_SUMMONER, 4, 7)

